//
//  HJRequestManager.swift
//  SwfitBase
//
//  Created by rubick on 2023/1/16.
//

import Foundation
import Moya
import Alamofire
import SwiftyJSON

///  网络请求相关

// MARK: error define
enum HJNetworkError: Error {
    case NetworkReachabilityError
    case NetworkRequestError
    case NetworkResponseError
    case NetworkUnexceptError
    case NetworkResponseParseError
    var localizedDescription: String {
        var desc = ""
        switch self {
        case .NetworkReachabilityError:
            desc = "No network connect"
        case .NetworkRequestError:
            desc = "Request error"
        case .NetworkResponseError:
            desc = "Response error"
        case .NetworkResponseParseError:
            desc = "Response parse error"
        default:
            desc = "Something error unexecpted"
        }
        return "ErrorMsg: \(desc)"
    }
}

// MARK: typealias
typealias successClosure = ((Dictionary<String, Any>) -> (Void))
typealias failureClosure = ((String, HJNetworkError) -> (Void))

// MARK: network connect
fileprivate var isNetworkConnect: Bool {
    get {
        let reachability = NetworkReachabilityManager()
        return reachability?.isReachable ?? true
    }
}

// MARK: provider

// normal provider
fileprivate let normalProvider = MoyaProvider<MultiTarget>(endpointClosure: hjEndpointClosure, requestClosure: hjRequestClosure, plugins: [hjRequestLoggerPlugin, hjRequestActivityPlugin])

// mock provider (response 将使用sampleData里边设置的mock数据)
fileprivate let mockProvider = MoyaProvider<MultiTarget>(endpointClosure: hjEndpointClosure, requestClosure: hjRequestClosure, stubClosure: hjMockStubClosure, plugins: [hjRequestActivityPlugin, hjRequestActivityPlugin])

// 请求Target为class, 仅作为示例方法
@available(*, deprecated, message: "Use `normalProvider` instead, This is just an example method")
fileprivate let oldProvider = MoyaProvider<HJBaseRequest>(endpointClosure: hjEndpointClosure, requestClosure: hjRequestClosure, plugins: [hjRequestActivityPlugin, hjRequestLoggerPlugin])

// 请求Target为class，mock provider
@available(*, deprecated, message: "Use `normalProvider` instead, This is just an example method")
fileprivate let oldMockProvider = MoyaProvider<HJBaseRequest>(endpointClosure: hjEndpointClosure, requestClosure: hjRequestClosure, stubClosure: hjMockStubClosure, plugins: [hjRequestActivityPlugin, hjRequestLoggerPlugin])

// MARK: request

func HJNetworkRequest(_ request: TargetType, completion: @escaping successClosure, failed: @escaping failureClosure, isMock: Bool = false) {
    if !isNetworkConnect {
        failed("No network connect", .NetworkReachabilityError)
    }
    //
    if (isMock) {
        mockProvider.request(MultiTarget(request)) { result in
            switch result {
            case let .success(response):
                do {
                    let jsonData = try JSON(data: response.data)
                    let resultData = jsonData.dictionary
                    completion(resultData!)
                } catch {
                    failed("json decode error", .NetworkResponseParseError)
                }
            case let .failure(error):
                failed(error.localizedDescription, .NetworkResponseError)
            }
        }
    } else {
        normalProvider.request(MultiTarget(request)) { result in
            switch result {
            case let .success(response):
                do {
                    let jsonData = try JSON(data: response.data)
                    let resultData = jsonData.dictionaryObject
                    completion(resultData!)
                } catch {
                    failed("json decode error", .NetworkResponseParseError)
                }
            case let .failure(error):
                failed(error.localizedDescription, .NetworkResponseError)
            }
        }
    }
}

func HJNetworkRequestOld(_ request: HJBaseRequest, completion: @escaping successClosure, failed: @escaping failureClosure, isMock: Bool = false) {
    if !isNetworkConnect {
        failed("No network connect", .NetworkReachabilityError)
    }
    //
    if (isMock) {
        oldMockProvider.request(request) { result in
            switch result {
            case let .success(response):
                do {
                    let jsonData = try JSON(data: response.data)
                    let resultData = jsonData.dictionary
                    completion(resultData!)
                } catch {
                    failed("json decode error", .NetworkResponseParseError)
                }
            case let .failure(error):
                failed(error.localizedDescription, .NetworkResponseError)
            }
        }
    } else {
        oldProvider.request(request) { result in
            switch result {
            case let .success(response):
                do {
                    let jsonData = try JSON(data: response.data)
                    let resultData = jsonData.dictionary
                    completion(resultData!)
                } catch {
                    failed("json decode error", .NetworkResponseParseError)
                }
            case let .failure(error):
                failed(error.localizedDescription, .NetworkResponseError)
            }
        }
    }
}

// 数组转JSON
struct JSONArrayEncoding: ParameterEncoding {
    static let `default` = JSONArrayEncoding()
    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var request = try urlRequest.asURLRequest()
        guard let json = parameters?["jsonArray"] else {
            return request
        }
        let data = try JSONSerialization.data(withJSONObject: json, options: [])
        if request.value(forHTTPHeaderField: "Content-Type") == nil {
            request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        }
        request.httpBody = data
        return request
    }
}


